﻿using System;
using System.Diagnostics;

using octalforty.Chinchillin.Shared.Deployment;
using octalforty.Chinchillin.Shared.Deployment.Metadata;
using octalforty.Chinchillin.Shared.Deployment.Resources;
using octalforty.Chinchillin.Shared.Deployment.Resources.Impl;

namespace octalforty.Chinchillin.Actions.Shell
{
    [Action(Name)]
    public class ExecAction : ActionBase
    {
        #region Private Constants
        private const string Name = "exec";
        private const string Command = "command";
        private const string Args = "args";
        private const string Timeout = "timeout";

        private static readonly ActionInfo actionInfo = new ActionInfo {
            Name = Name,
            Arguments = new[]
                {
                    new ActionArgumentInfo(Command, ActionArgumentType.String),
                    new ActionArgumentInfo(Args, ActionArgumentType.String),
                    new ActionArgumentInfo(Timeout, ActionArgumentType.String)
                }
        };
        #endregion

        #region Public Properties
        public IResourceProvider LocalResourceProvider
        { get; set; }

        public IFileSystemManager FileSystemManager
        { get; set; }
        #endregion

        public ExecAction() : 
            base(actionInfo)
        {
        }

        public override void Execute(IActionExecutionContext executionContext)
        {
            try
            {
                var command = (string)executionContext.Arguments[Command];
                var args = executionContext.Arguments.ContainsKey(Args) ?
                    (string)executionContext.Arguments[Args] :
                    null;
                var timeoutValue = executionContext.Arguments.ContainsKey(Timeout) ?
                    (string)executionContext.Arguments[Timeout] :
                    "30";

                var timeout = TimeSpan.Parse(timeoutValue.Contains(":") ? timeoutValue : "00:00:" + timeoutValue);

                TracingManager.TraceEvent(executionContext, TraceEventType.Information, 0,
                    string.Format("Executing command '{0}' with arguments '{1}' and timeout {2}", command, args, timeout));

                var processStart = new ProcessStartInfo(command, args) {
                    CreateNoWindow = true, 
                    ErrorDialog = false
                };

                var process = Process.Start(processStart);
                if(process != null)
                    process.WaitForExit((int)timeout.TotalMilliseconds);
            } // try
            catch(Exception e)
            {
                TracingManager.TraceEvent(executionContext, TraceEventType.Error, 0, e.ToString());
                throw;
            } // catch
        }
    }
}
